#include "declare.hpp"

// 显示主菜单
void MapSystem::_DisPlayMenu()
{
    std::cout << "+-----------------------------------------------+" << std::endl;
    std::cout << "|                欢迎光临                      |" << std::endl;
    std::cout << "|          电子地图管理系统                    |" << std::endl;
    std::cout << "+-----------------------------------------------+" << std::endl;
    std::cout << "|  请选择服务                                   |" << std::endl;
    std::cout << "|  1. 读取文件         - 载入地图数据         |" << std::endl;
    std::cout << "|  2. 排序             - 对地图数据进行排序   |" << std::endl;
    std::cout << "|  3. 检索             - 查找特定地点         |" << std::endl;
    std::cout << "|  4. 更新             - 更新地图信息         |" << std::endl;
    std::cout << "|  0. 退出             - 退出地图系统             |" << std::endl;
    std::cout << "+-----------------------------------------------+" << std::endl;
    std::cout << "| 输入选项并按回车:                            |" << std::endl;
    std::cout << "+-----------------------------------------------+" << std::endl;
}

// 提供主服务
void MapSystem::Main_Service()
{
    do
    {
        _DisPlayMenu(); // 显示服务菜单
        _Input();       // 选择服务
        switch (_input)
        {
        case READ:
        {
            FileFormat format = _SelectFileFormat(); // 选择文件格式
            _ReadFile(format);                       // 读取文件
            break;
        }
        case SORT:
            _SortService(); // 排序服务
            break;
        case SEARCH:
            _SearchService(); // 查找服务
            break;
        case UPDATE:
            _UpdataService(); // 更新服务
            break;
        case EXIT:
            _ExitCase(); // 退出系统
            break;
        default:
            _ErrorCase(); // 错误情况处理
            break;
        }
    } while (_flag);
}

bool MapSystem::_Input()
{
    std::cout << "Please Enter@> ";
    std::cin >> _input;
    return true;
}

void MapSystem::_ExitCase()
{
    _flag = false;
    _log(INFO, "退出系统");
}

void MapSystem::_ErrorCase()
{
    _flag = false;
    _log(ERROR, "选择的服务不存在,退出系统");
}

// 显示文件格式选择菜单
void MapSystem::_DisPlayFileSelectMenu()
{
    std::cout << "======================================" << std::endl;
    std::cout << "           选择文件格式           " << std::endl;
    std::cout << "======================================" << std::endl;
    std::cout << "1. 文本文件    -- GTBL.txt" << std::endl;
    std::cout << "2. 二进制文件  -- GTBL.bin " << std::endl;
    std::cout << "======================================" << std::endl;
    std::cout << "请选择读取文件格式@> ";
}

// 选择文件格式
FileFormat MapSystem::_SelectFileFormat()
{
    int fileType;
    _DisPlayFileSelectMenu();
    std::cin >> fileType;
    switch (fileType)
    {
    case 1:
        return FileFormat::TEXT;
    case 2:
        return FileFormat::BINARY;
    default:
        _log(WARNING, "无效的文件类型选择，默认选择文本文件");
        return FileFormat::TEXT; // 默认选择文本文件
    }
}

// 读取文件格式
void MapSystem::_ReadFile(FileFormat format)
{
    switch (format)
    {
    case FileFormat::TEXT:
        _ReadTextFile();
        break;
    case FileFormat::BINARY:
        _ReadBinaryFile();
        break;
    default:
        _log(WARNING, "Unsupported file format");
        break;
    }
}

// 显示排序菜单
void MapSystem::_DisPlaySortMenu()
{
    std::cout << std::endl;
    std::cout << "+-----------------------------------------------+" << std::endl;
    std::cout << "|                排序菜单                     |" << std::endl;
    std::cout << "+-----------------------------------------------+" << std::endl;
    std::cout << "|  1. 插入排序 - 最简单的排序方法            |" << std::endl;
    std::cout << "|  2. 希尔排序 - 改进的插入排序              |" << std::endl;
    std::cout << "|  3. 选择排序 - 选择最小元素进行排序        |" << std::endl;
    std::cout << "|  4. 冒泡排序 - 相邻元素两两比较            |" << std::endl;
    std::cout << "|  5. 快速排序 - 高效的分治排序算法          |" << std::endl;
    std::cout << "|  6. 归并排序 - 将数据分成两部分后合并      |" << std::endl;
    std::cout << "|  0. 退出     - 返回主菜单               |" << std::endl;
    std::cout << "+-----------------------------------------------+" << std::endl;
    std::cout << "|  请选择一个选项 (输入数字):                 |" << std::endl;
    std::cout << "+-----------------------------------------------+" << std::endl;
}

// 准备数组数据
void MapSystem::_ListToVector()
{
    if (_nodeList.empty())
    {
        _log(WARNING, "未读取文件数据,没有需要操作的数据");
        return;
    }
    _vector_array.clear();
    for (auto &node : this->_nodeList)
    {
        _vector_array.push_back(node);
    }
}

// 排序服务
void MapSystem::_SortService()
{
    size_t option = 0;
    this->_DisPlaySortMenu();
    do
    {
        std::cout << "请选择排序类型:@> ";
        std::cin >> option;
        clock_t begin, end;
        std::string sortName;
        switch (option)
        {
        case InsertSort:
            this->_ListToVector(); // 为了保证能够准确测试各排序性能，必须每次都刷新数组数据
            sortName = "插入排序";
            begin = clock();
            _InsertSort_Implement();
            end = clock();
            break;
        case ShellSort:
            this->_ListToVector();
            sortName = "希尔排序";
            begin = clock();
            _ShellSort_Implement();
            end = clock();
            break;
        case SelectSort:
            this->_ListToVector();
            sortName = "选择排序";
            begin = clock();
            _SelectSort_Implement();
            end = clock();
            break;
        case BubbleSort:
            this->_ListToVector();
            sortName = "冒泡排序";
            begin = clock();
            _BubbleSort_Implement();
            end = clock();
            break;
        case QuickSort:
            this->_ListToVector();
            sortName = "快速排序";
            begin = clock();
            _QuickSort_Implement(0, _vector_array.size() - 1);
            end = clock();
            break;
        case MergeSort:
            this->_ListToVector();
            sortName = "归并排序";
            begin = clock();
            _MergeSort_Implement(0, _vector_array.size() - 1);
            end = clock();
            break;
        case EXIT:
            this->_log(INFO, "退出排序程序");
            return;
        default:
            this->_log(ERROR, "选择错误,退出排序程序");
            return;
        }

        // 计算时间差并转换为 ms
        double time = (end - begin) * 1000 / CLOCKS_PER_SEC;
        _log(INFO, "[%s]-执行时间: %.3f ms", sortName.c_str(), time);
        // 排序后自动更新写入文件
        this->_WriteFile();
    } while (option);
}

// 查找功能菜单
void MapSystem::_DisPlaySearchMenu()
{
    std::cout << "======================================" << std::endl;
    std::cout << "           选择查找方式           " << std::endl;
    std::cout << "======================================" << std::endl;
    std::cout << std::setw(5) << "1." << " 遍历查找" << std::endl;
    std::cout << std::setw(5) << "2." << " 二分查找" << std::endl;
    std::cout << std::setw(5) << "3." << " 哈希查找" << std::endl;
    std::cout << std::setw(5) << "4." << " 二叉搜索树查找" << std::endl;
    std::cout << std::setw(5) << "0." << " 返回主菜单" << std::endl;
    std::cout << "======================================" << std::endl;
    std::cout << "请选择查找方式@> ";
}

// 输入要查找的linkID
void MapSystem::_InputSearch(INT32U &linkID)
{
    std::cout << "请输入要查找的 LinkID: ";
    std::cin >> linkID;
}

// 查找服务
void MapSystem::_SearchService()
{
    while (true)
    {
        _DisPlaySearchMenu();
        int choice;
        std::cin >> choice;

        if (choice == EXIT)
        {
            this->_log(INFO, "退出查找程序");
            return;
        }
        // 没有排序数组是空直接来查找,就填充数组数据用来搜索
        if (_vector_array.empty())
            this->_ListToVector();
        INT32U linkID;

        // 记录开始和结束时间
        std::chrono::steady_clock::time_point begin, end;
        std::string searchName;

        switch (choice)
        {
        case Order:
            _InputSearch(linkID);
            searchName = "遍历查找";
            begin = std::chrono::steady_clock::now();
            _SearchWithOrder(linkID);
            end = std::chrono::steady_clock::now();
            break;
        case Binary:
            _InputSearch(linkID);
            searchName = "二分查找";
            begin = std::chrono::steady_clock::now();
            _SearchWithBinary(linkID);
            end = std::chrono::steady_clock::now();
            break;
        case Hash:
            _InputSearch(linkID);
            searchName = "哈希查找";
            begin = std::chrono::steady_clock::now();
            _SearchWithHash(linkID);
            end = std::chrono::steady_clock::now();
            break;
        case SearchTree:
            _InputSearch(linkID);
            searchName = "二叉排序树查找";
            begin = std::chrono::steady_clock::now();
            _SearchWithTree(linkID);
            end = std::chrono::steady_clock::now();
            break;
        default:
            this->_log(ERROR, "选择错误,退出搜索程序");
            return;
        }
        if (searchName == "遍历查找")
        {
            // 遍历查找就以微秒显示
            auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count();
            _log(INFO, "[%s]-执行时间: %lld µs", searchName.c_str(), duration);
        }
        else
        {
            // 计算实际耗时（包括所有操作时间）并以毫秒显示
            auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count();
            _log(INFO, "[%s]-执行时间: %lld ms", searchName.c_str(), duration);
        }
    }
}

// 显示更新服务菜单
void MapSystem::_DisPlayUpdataMenu()
{
    std::cout << "======================================" << std::endl;
    std::cout << "           选择更新服务           " << std::endl;
    std::cout << "======================================" << std::endl;
    std::cout << std::setw(5) << "1." << " 添加记录" << std::endl;
    std::cout << std::setw(5) << "2." << " 删除记录" << std::endl;
    std::cout << std::setw(5) << "3." << " 修改记录" << std::endl;
    std::cout << std::setw(5) << "0." << " 返回主菜单" << std::endl;
    std::cout << "======================================" << std::endl;
    std::cout << "请选择服务@> ";
}

// 提供更新服务
void MapSystem::_UpdataService()
{
    while (true)
    {
        _DisPlayUpdataMenu();
        int choice;
        std::cin >> choice;

        if (choice == EXIT)
        {
            this->_log(INFO, "退出更新程序");
            return;
        }
        // 没有排序数组是空直接来更新,就填充数组数据
        if (_vector_array.empty())
            this->_ListToVector();
        // 插入记录时填充字段时产生随机数的种子
        srand((unsigned int)time(nullptr));

        switch (choice)
        {
        case AddRecord:
            this->_AddRecord(); // 添加记录
            break;
        case DeleteRecord:
            this->_DeleteRecord(); // 删除记录
            break;
        case ModifyRecord:
            this->_ModifyRecord(); // 修改记录
            break;
        default:
            this->_log(ERROR, "选择错误,退出修改程序");
            return;
        }
        // 更新后自动更新写入文件
        this->_WriteFile();
    }
}
